#include "Root.h"
#include "WindowEventUtilities.h"

namespace DreamEngine
{
CRoot::CRoot(void):
m_pCurRenderSystem(MATH_NULL),
m_pInputSystem(MATH_NULL),
m_pSceneManager(MATH_NULL),
m_pMaterialManager(MATH_NULL),
m_pDynLibManager(MATH_NULL),
m_pMeshManager(MATH_NULL)
{
	m_pDynLibManager	= new CDynLibManager;
}


CRoot::~CRoot(void)
{
	
}

CRoot& CRoot::Instance(void)
{	
	return (*m_singleton); 
}

CRoot* CRoot::InstancePtr(void)
{ 
	return m_singleton; 
}


void CRoot::SetRenderSystem(CRenderSystem* pRenderSystem)
{
	m_pCurRenderSystem = pRenderSystem;
}

void CRoot::SetInputSystem(CInputSystem* pInputSystem)
{
	m_pInputSystem = pInputSystem;
}

bool CRoot::LoadPlugin(const CString& name)
{
	if (m_pDynLibManager != MATH_NULL)
	{
		CDynLib* pDynLib = m_pDynLibManager->Load(name);
		if (pDynLib!=MATH_NULL)
		{
			DLL_PLUGIN_FUNC pFunc = (DLL_PLUGIN_FUNC)(pDynLib->GetSymbol("dllStartPlugin"));

			if (pFunc != MATH_NULL)
			{
				pFunc();
				return true;
			}
		}
	}

	return false;
}

void CRoot::Initialize(const CString& windowName, m_uint16 width, m_uint16 heigth)
{
	if (m_pCurRenderSystem != MATH_NULL)
		m_pCurRenderSystem->CreateRenderWindow(windowName, width, heigth);

	m_pSceneManager		= new CSceneManager(m_pCurRenderSystem);
	m_pMaterialManager	= new CMaterialManager;
	m_pMeshManager		= new CMeshManager(m_pCurRenderSystem);
	m_pRegisterData		= new CRegisterData;

}

void CRoot::ShutDown()
{
	SAFE_DELETE(m_pRegisterData);

	m_pSceneManager->OnDestory();
	SAFE_DELETE(m_pSceneManager);

	m_pMaterialManager->DestoryAll();
	SAFE_DELETE(m_pMaterialManager);

	m_pDynLibManager->FreeAll();
	SAFE_DELETE(m_pDynLibManager);

	m_pMeshManager->DestroyAll();
	SAFE_DELETE(m_pMeshManager);
}

void CRoot::InstallPlugin(CPLugin* pLugin)
{
	if (pLugin==MATH_NULL) return;
	
	pLugin->Install();
	m_plugins.push_back(pLugin);
}

void CRoot::UnInstallPlugin(CPLugin* pLugin)
{
	PluginLst::iterator iter = find(m_plugins.begin(), m_plugins.end(), pLugin);
	
	if (iter != m_plugins.end())
	{
		(*iter)->Uninstall();
		m_plugins.erase(iter);
	}
}

void CRoot::Go()
{
	if (m_pCurRenderSystem==MATH_NULL)return;

	CRenderWindow* pRenderWindow = m_pCurRenderSystem->GetActiveRenderWindow();

	if (pRenderWindow != MATH_NULL)
	{
		pRenderWindow->ShowWindow();
	}

	while (true)
	{
		CWindowEventUtilities::PumpMessage();

		if (CWindowEventUtilities::IsQuit())break;

		Loop();
	}
}

void CRoot::Loop()
{
	if (m_pCurRenderSystem==MATH_NULL)return;

	CRenderWindow* pRenderWindow = m_pCurRenderSystem->GetActiveRenderWindow();
	CRenderTarget::ListenerTargetIter& rtEventLst = pRenderWindow->GetListenerIter();

	//start render
	rtEventLst.MoveToBegin();
	while (rtEventLst.HasMore())
	{
		rtEventLst.Current()->OnRenderStart(pRenderWindow);
		rtEventLst.Next();
	}
	m_pCurRenderSystem->BeginFrame();

	//rendering
	if (m_pSceneManager != MATH_NULL)
		m_pSceneManager->OnRender();

	rtEventLst.MoveToBegin();
	while (rtEventLst.HasMore())
	{
		rtEventLst.Current()->OnRender(pRenderWindow);
		rtEventLst.Next();
	}

	//end rendering
	m_pCurRenderSystem->EndFrame();
	rtEventLst.MoveToBegin();
	while (rtEventLst.HasMore())
	{
		rtEventLst.Current()->OnRenderEnd(pRenderWindow);
		rtEventLst.Next();
	}

	pRenderWindow->UpdateFPS();
}

}